package com.lzc.lblog.lblog.service.impl;

import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.lzc.lblog.lblog.entity.MPost;
import com.lzc.lblog.lblog.mapper.MPostMapper;
import com.lzc.lblog.lblog.service.MPostService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.lzc.lblog.lblog.utils.RedisUtil;
import com.lzc.lblog.lblog.vo.PostVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.ZSetOperations;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author lzczzzz
 * @since 2020-12-02
 */
@Service
public class MPostServiceImpl extends ServiceImpl<MPostMapper, MPost> implements MPostService {

    @Autowired
    private MPostMapper mPostMapper;
    @Autowired
    private RedisUtil redisUtil;

    /**
     * 首页博客分页显示
     * @param page
     * @param categoryId
     * @param level
     * @param recommend
     * @param userId
     * @return
     */
    @Override
    public IPage<PostVo> paging(Page page, Long categoryId, Integer level, Boolean recommend, Long userId,String order,Integer status) {
        if(level==null) level=-1;
        //当状态为0的时候查询的是所有 所有把它设为0
        if(!StringUtils.isEmpty(status)){
            if(status==0){
                status=null;
            }
        }
        QueryWrapper<PostVo> postVoQueryWrapper = new QueryWrapper<PostVo>()
                .eq(categoryId!=null,"category_id",categoryId)
                .eq(level==0,"level",0)
                .ge(level>0,"level",level)
                .eq(recommend!=null,"recommend",recommend)
                .eq(userId!=null,"user_id",userId)
                .eq(status!=null,"p.status",status)
                .orderByDesc(order!=null,order);

        return mPostMapper.page(page,postVoQueryWrapper);
    }

    /**
     * 获取博客详情
     * @param id
     * @return
     */
    @Override
    public PostVo selectDetail(Long id) {
        return mPostMapper.selectDetail(id);
    }

    /**
     * 首页初始化本周热议
     */
    @Override
    public void initWeek() {
        //先获取7天内的文章信息
        List<MPost> mPosts = mPostMapper.selectList(new QueryWrapper<MPost>()
                .ge("created", DateUtil.lastWeek())
                .select("id", "title", "comment_count","view_count","created", "user_id"));
        //初始化文章7天内每天的评论量 最后汇总 排行就可以
        for (MPost post : mPosts) {
            //文章创建时间作为key
            String key="postDay:rank"+DateUtil.format(post.getCreated(), DatePattern.NORM_DATE_PATTERN);
            //文章id作为值 评论数量作为分数
            redisUtil.zSet(key,post.getId(),post.getCommentCount());
            //设置过期时间
            long between = DateUtil.between(new Date(), post.getCreated(), DateUnit.DAY);
            //得到过期秒
            long expire=(7-between)*24*60*60;
            redisUtil.expire(key,expire);
            //缓存文章的基本信息 以json格式
            this.cachePostByJson(post,expire);
        }
        //汇总
        this.weekRankForCommentCount();

    }

    /**
     * 得到本周热议文章
     * @return
     */
    @Override
    public List<MPost> hotsOnWeek() {
        Set<ZSetOperations.TypedTuple> zSetRank = redisUtil.getZSetRank("week:rank", 0, 6);
        List<MPost> mPosts = zSetRank.stream().map(item -> {
            String  postKey = "post:"+item.getValue();
            MPost post = (MPost) redisUtil.get(postKey);
            return post;
        }).collect(Collectors.toList());
        return mPosts;
    }

    /**
     * 文章浏览累加
     * @param postVo
     */
    @Override
    public void viewCountIncr(PostVo postVo) {
        String postKey = "post:" + postVo.getId();
        MPost mPost= (MPost) redisUtil.get(postKey);
        if(mPost.getViewCount()!=null){
            postVo.setViewCount(mPost.getViewCount()+1);
        }else {
            postVo.setViewCount(postVo.getViewCount()+1);
        }
        redisUtil.set(postKey,postVo);
    }

    /**
     * 热议文章评论汇总
     */
    private void weekRankForCommentCount() {
        String destKey = "week:rank";
        String currKey="postDay:rank"+DateUtil.format(new Date(), DatePattern.NORM_DATE_PATTERN);
        List<String> othersKeys=new ArrayList<>();
        for(int i=-6;i<0;i++){
            othersKeys.add("postDay:rank"+DateUtil.format(DateUtil.offsetDay(new Date(),i), DatePattern.NORM_DATE_PATTERN));
        }
        redisUtil.zUnionAndStore(currKey,othersKeys,destKey);
    }

    /**
     * 缓存热议文章
     * @param post
     * @param expire
     */
    private void cachePostByJson(MPost post, long expire) {
        String key="post:"+post.getId();
        if(!redisUtil.hasKey(key)){
            redisUtil.set(key,post,expire);
        }
    }
}
